<?php
/*
 * ===========================================
 * ================【simpler】================
 * ===========================================
 * file： xxx.php
 * description：
 * author：wanghua
 * email：382379437@qq.com
 * createTime：{2018/6/11} {17:48} 
 * updateTime：0000.00.00
 */

namespace wanghua\general_utility_tools_php\wechat;

use wanghua\general_utility_tools_php\tool\Tools;

class WechatLogic
{

    protected $wechatConfig = [];
    protected $access_token_path = '';//票据存储位置，必须且具有读写权限

    /**
     * 初始化
     * UserAuth constructor.
     * @param array $wechatConfig 微信全局配置，eg：appid等
     * @param string $access_token_path access_token票据存储相对位置
     */
    public function __construct(array $wechatConfig, string $access_token_path)
    {

        $this->wechatConfig = $wechatConfig;//全局配置
        $this->access_token_path = Tools::get_root_path().$access_token_path;//access_token票据存储位置
        if(!file_exists($this->access_token_path)){
            mkdir($this->access_token_path, 0777, true);
            file_put_contents($this->access_token_path.'/access_token.txt','');
        }
        $this->checkParams();


    }

    /**
     * desc：检查参数
     * author：wh
     * @throws \Exception
     */
    protected function checkParams(){
        if(empty($this->wechatConfig['appid'])){
            throw new \Exception('请设置appid');
        }
        if(empty($this->wechatConfig['app_secret'])){
            throw new \Exception('请设置app_secret');
        }

    }
    /**
     * description：获取票据
     * author：wanghua
     */
    function getAccessToken(){
        $save_path = Tools::get_root_path().$this->wechatConfig['access_token_path'].'/access_token.txt';

        $access_token = file_get_contents($save_path);
        //获取票据，并验证是否超时，保证票据有效（全局唯一）
        if(!trim($access_token)){
            return $this->getAccessTokenNow($save_path);//实时获取
        }else{
            //是否过期
            $exp = explode('==', $access_token);
            if(time() - $exp[1]*1 >= 6900){//允许提前5分钟刷新
                return $this->getAccessTokenNow($save_path);//实时获取
            }else{
                return $exp[0];
            }
        }
    }

    /**
     * description：实时获取【基础-非网页授权token】
     * author：wanghua
     */
    function getAccessTokenNow($save_path){
        try{
            //实时获取
            $appid = $this->wechatConfig['appid'];
            $appsecret = $this->wechatConfig['app_secret'];
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret";
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($ch);
            curl_close($ch);
            $jsoninfo = json_decode($output, true);

            file_put_contents($save_path, $jsoninfo["access_token"].'=='.time());//永久保存
            return $jsoninfo["access_token"];
        }catch (\Exception $e){
            Tools::log_to_write_txt(['error_title'=>'[错误]获取票据出错:'.$e->getMessage(),'error_info'=>$e->getTraceAsString()]);
            return false;
        }
    }

    /**
     * description：公共获取openid 不要在其它地方单独获取
     * author：wanghua
     */
    /**
     * description：基础openid
     * author：wanghua
     */
    function getBaseOpenid(){
        require_once Tools::get_root_path()."library/php_sdk_v3/example/WxPay.JsApiPay.php";

        //$openId = session('wx_user_info.openid');
        //if(!$openId){
            $tools = new \JsApiPay();
            $openId = $tools->GetOpenid();//获取
            //cookie('openId', $openId);//全局存储
        //}
        return $openId;
    }

    /**
     * 【非基础token】
     * description：（第2步）通过code换取网页授权access_token，
     * 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
     * 得到的数据：
    array(6) {
    ["access_token"]=>
    string(89) "10_ckJ3HZCePXha8yKNCaBEqZnemtt_bWc17IlIAwLh1bewR-3ilWybde_OxjevoO7QYOJzeqqiAL71Vv65vtO-zg"
    ["expires_in"]=>
    int(7200)
    ["refresh_token"]=>
    string(89) "10_OHKwmcQPj6UEt6O0hQiXgIqpdaFkGQNgrbB4zfCIjiGG_-bLqEPDXju4cXVH4FvDuhqG_N5h_OCY1LwZNTNU4g"
    ["openid"]=>
    string(28) "o5_r60xfL0speOoDVcAcrfX24wTw"
    ["scope"]=>
    string(15) "snsapi_userinfo"
    ["unionid"]=>
    string(28) "o20U21BMNw_3i-jpGjudYxfud6uE"
    }
     * @param $code 来自用户授权code
     * author：wanghua
     */
    function usrAccessToken($code){
        $appid = $this->wechatConfig['appid'];
        $secret = $this->wechatConfig['app_secret'];
        //获取code后，请求以下链接获取access_token
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
        $res_data = Tools::curl_get($url);
        $data = json_decode($res_data['data'], true);
        return $data;
    }

    /**
     * description：判断用户是否已关注(未关注返回false)
     * 如果已关注则返回：
     * array(17) {
    ["subscribe"]=>
    int(1)
    ["openid"]=>
    string(28) "o5_r60xfL0speOoDVcAcrfX24wTw"
    ["nickname"]=>
    string(6) "展望"
    ["sex"]=>
    int(1)
    ["language"]=>
    string(5) "zh_CN"
    ["city"]=>
    string(6) "渝中"
    ["province"]=>
    string(6) "重庆"
    ["country"]=>
    string(6) "中国"
    ["headimgurl"]=>
    string(136) "http://thirdwx.qlogo.cn/mmopen/mdcJghD8vWuRYTs1qGpgsqIiatsxNEXRKcDqEvh3rIyEpbiaXIXmyHNVlRONKicRl3I3HoWygcoAS8gAOJtc2gMic9ibI6DNXwSLl/132"
    ["subscribe_time"]=>
    int(1529396683)
    ["unionid"]=>
    string(28) "o20U21BMNw_3i-jpGjudYxfud6uE"
    ["remark"]=>
    string(0) ""
    ["groupid"]=>
    int(0)
    ["tagid_list"]=>
    array(0) {
    }
    ["subscribe_scene"]=>
    string(22) "ADD_SCENE_PROFILE_CARD"
    ["qr_scene"]=>
    int(0)
    ["qr_scene_str"]=>
    string(0) ""
    }
     * author：wanghua
     * @return mixed
     */
    function checkIsCare(){
        $openId = session('wx_user_info.openid');
        $access_token = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$access_token.'&openid='.$openId.'&lang=zh_CN';
        $res_data = Tools::curl_get($url);
        $data = json_decode($res_data['data'], true);
        if(empty($data['subscribe'])) return false;
        return $data;
    }

    /**
     * description：实时获取jsapi_ticket
     * author：wanghua
     */
    function getJsapiTicketNow(){
        $access_token = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$access_token.'&type=jsapi';
        if(!file_exists($this->wechatConfig['js_api_ticket_path'])){
            mkdir($this->wechatConfig['js_api_ticket_path'], 0777, true);
            file_put_contents($this->wechatConfig['js_api_ticket_path'].'/js_api_ticket.txt','');
        }
        $data = json_decode(file_get_contents($url), true);
        if($data['errcode'])return false;
        file_put_contents($this->wechatConfig['js_api_ticket_path'].'/js_api_ticket.txt', $data['ticket'].'=='.time());//永久保存
        return $data['ticket'];
    }
    /**
     * description：获取JsapiTicket
     * author：wanghua
     */
    function getJsapiTicket(){
        $save_path = Tools::get_root_path().$this->wechatConfig['js_api_ticket_path'].'/js_api_ticket.txt';

        $token = file_get_contents($save_path);
        //获取票据，并验证是否超时，保证票据有效（全局唯一）
        if(!trim($token)){
            return $this->getJsapiTicketNow($save_path);//实时获取
        }else{
            //是否过期
            $exp = explode('==', $token);
            if(time() - $exp[1]*1 >= 6900){//允许提前5分钟刷新
                return $this->getJsapiTicketNow($save_path);//实时获取
            }else{
                return $exp[0];
            }
        }
    }

    /**
     * description：微信常规签名算法
     * author：wanghua
     */
    function getSignature($param){
        if(!$param || !is_array($param))return false;
        if(false !== strpos($param['url'], '#')){
            $exp = explode('#', $param['url']);
            if($param['url'])$param['url'] = $exp[0];
        }
        ksort($param);
        $string1 = '';
        foreach ($param as $k=>$v){
            $string1.= $k.'='.$v.'&';
        }
        $string1 = substr($string1, 0, strlen($string1)-1);
        $signature = sha1($string1);
        return $signature;
    }

    /**
     * description：JS-SDK使用权限签名算法
     * 文档地址：
     * https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62
     *
     * author：wanghua
     * @param $jspai_ticket
     * @return array
     */
    function getOption(){
        $jspai_ticket = $this->getJsapiTicket();//获取票据
        $options = [
            'noncestr'=>Tools::rand_str(8,1),
            'jsapi_ticket'=>$jspai_ticket,
            'timestamp'=>time(),
            'url'=>request()->domain().request()->url()
        ];
        $sign = $this->getSignature($options);//签名

        $options['debug'] = false;
        $options['appId'] = $this->wechatConfig['appid'];
        $options['signature'] = $sign;
        //常用接口-需要其它接口添加进来即可
        $options['jsApiList'] = [
            //'onMenuShareTimeline',//分享到朋友圈
            //'onMenuShareAppMessage',//分享给朋友
            'updateAppMessageShareData',
            //'onMenuShareQQ',//分享到QQ
            //'onMenuShareWeibo',//分享到腾讯微博
            //'onMenuShareQZone',//分享到QQ空间
        ];
        unset($options['url']);//参与算法完成后删除
        $noncestr = $options['noncestr'];
        unset($options['noncestr']);
        $options['nonceStr'] = $noncestr;
        return $options;
    }
}